 /*******************************************************************************
  * Copyright (c) 2005, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
  * Contributors:
  * IBM Corporation - initial API and implementation
  *******************************************************************************/

 package org.eclipse.ui.internal.menus;

 import java.util.ArrayList ;
 import java.util.Collection ;
 import java.util.HashMap ;
 import java.util.HashSet ;
 import java.util.Iterator ;
 import java.util.List ;
 import java.util.Map ;

 import org.eclipse.core.commands.Category;
 import org.eclipse.core.commands.Command;
 import org.eclipse.core.commands.CommandEvent;
 import org.eclipse.core.commands.ICommandListener;
 import org.eclipse.core.commands.IHandler;
 import org.eclipse.core.commands.ParameterizedCommand;
 import org.eclipse.core.commands.State;
 import org.eclipse.core.expressions.Expression;
 import org.eclipse.core.runtime.IConfigurationElement;
 import org.eclipse.core.runtime.IExtensionRegistry;
 import org.eclipse.core.runtime.IRegistryChangeEvent;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.LegacyActionTools;
 import org.eclipse.jface.bindings.Binding;
 import org.eclipse.jface.bindings.Scheme;
 import org.eclipse.jface.bindings.keys.IKeyLookup;
 import org.eclipse.jface.bindings.keys.KeyBinding;
 import org.eclipse.jface.bindings.keys.KeyLookupFactory;
 import org.eclipse.jface.bindings.keys.KeySequence;
 import org.eclipse.jface.bindings.keys.KeyStroke;
 import org.eclipse.jface.commands.RadioState;
 import org.eclipse.jface.commands.ToggleState;
 import org.eclipse.jface.contexts.IContextIds;
 import org.eclipse.jface.menus.IMenuStateIds;
 import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.SelectionEnabler;
 import org.eclipse.ui.commands.ICommandService;
 import org.eclipse.ui.handlers.IHandlerActivation;
 import org.eclipse.ui.handlers.IHandlerService;
 import org.eclipse.ui.internal.ActionExpression;
 import org.eclipse.ui.internal.WorkbenchMessages;
 import org.eclipse.ui.internal.WorkbenchPlugin;
 import org.eclipse.ui.internal.expressions.LegacyActionExpressionWrapper;
 import org.eclipse.ui.internal.expressions.LegacyActionSetExpression;
 import org.eclipse.ui.internal.expressions.LegacyEditorContributionExpression;
 import org.eclipse.ui.internal.expressions.LegacySelectionEnablerWrapper;
 import org.eclipse.ui.internal.expressions.LegacyViewContributionExpression;
 import org.eclipse.ui.internal.expressions.LegacyViewerContributionExpression;
 import org.eclipse.ui.internal.handlers.ActionDelegateHandlerProxy;
 import org.eclipse.ui.internal.handlers.IActionCommandMappingService;
 import org.eclipse.ui.internal.keys.BindingService;
 import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
 import org.eclipse.ui.internal.services.RegistryPersistence;
 import org.eclipse.ui.keys.IBindingService;

 /**
  * <p>
  * A static class for reading actions from the registry. Actions were the
  * mechanism in 3.1 and earlier for contributing to menus and tool bars in the
  * Eclipse workbench. They have since been replaced with commands.
  * </p>
  * <p>
  * This class is not intended for use outside of the
  * <code>org.eclipse.ui.workbench</code> plug-in.
  * </p>
  *
  * @since 3.2
  */
 public final class LegacyActionPersistence extends RegistryPersistence {

     /**
      * The index of the action set elements in the indexed array.
      *
      * @see LegacyActionPersistence#read()
      */
     private static final int INDEX_ACTION_SETS = 0;

     /**
      * The index of the editor contribution elements in the indexed array.
      *
      * @see LegacyActionPersistence#read()
      */
     private static final int INDEX_EDITOR_CONTRIBUTIONS = 1;

     /**
      * The index of the object contribution elements in the indexed array.
      *
      * @see LegacyActionPersistence#read()
      */
     private static final int INDEX_OBJECT_CONTRIBUTIONS = 2;

     /**
      * The index of the view contribution elements in the indexed array.
      *
      * @see LegacyActionPersistence#read()
      */
     private static final int INDEX_VIEW_CONTRIBUTIONS = 3;

     /**
      * The index of the viewer contribution elements in the indexed array.
      *
      * @see LegacyActionPersistence#read()
      */
     private static final int INDEX_VIEWER_CONTRIBUTIONS = 4;


     /**
      * Reads the visibility element for a contribution from the
      * <code>org.eclipse.ui.popupMenus</code> extension point.
      *
      * @param parentElement
      * The contribution element which contains a visibility
      * expression; must not be <code>null</code>.
      * @param parentId
      * The identifier of the parent contribution; may be
      * <code>null</code>.
      * @param warningsToLog
      * The list of warnings to be logged; must not be
      * <code>null</code>.
      * @return An expression representing the visibility element; may be
      * <code>null</code>.
      */
     private static final Expression readVisibility(
             final IConfigurationElement parentElement, final String parentId,
             final List warningsToLog) {
         final IConfigurationElement[] visibilityElements = parentElement
                 .getChildren(TAG_VISIBILITY);
         if ((visibilityElements == null) || (visibilityElements.length == 0)) {
             return null;
         }

         if (visibilityElements.length != 1) {
             addWarning(warningsToLog,
                     "There can only be one visibility element", parentElement, //$NON-NLS-1$
 parentId);
         }

         final IConfigurationElement visibilityElement = visibilityElements[0];
         final ActionExpression visibilityActionExpression = new ActionExpression(
                 visibilityElement);
         final LegacyActionExpressionWrapper wrapper = new LegacyActionExpressionWrapper(
                 visibilityActionExpression, null);
         return wrapper;
     }

     /**
      * The binding manager which should be populated with bindings from actions;
      * must not be <code>null</code>.
      */
     private final BindingService bindingService;



     /**
      * The command service which is providing the commands for the workbench;
      * must not be <code>null</code>.
      */
     private final ICommandService commandService;

     /**
      * The handler activations that have come from the registry. This is used to
      * flush the activations when the registry is re-read. This value is never
      * <code>null</code>
      */
     private final Collection handlerActivations = new ArrayList ();

     /**
      * The menu contributions that have come from the registry. This is used to
      * flush the contributions when the registry is re-read. This value is never
      * <code>null</code>
      */
     private final Collection menuContributions = new ArrayList ();

     /**
      * The service locator from which services can be retrieved in the future;
      * must not be <code>null</code>.
      */
     private final IWorkbenchWindow window;
     
     /**
      * Help action sets with enable/disable.
      */
     private ICommandListener actionSetListener = new ICommandListener() {
         public void commandChanged(CommandEvent commandEvent) {
             Command cmd = commandEvent.getCommand();
             String commandId = cmd.getId();
             Binding binding = (Binding) commandIdToBinding.get(commandId);
             if (binding != null) {
                 if (cmd.isEnabled()) {
                     if (!actionSetActiveBindings.contains(binding)) {
                         bindingService.addBinding(binding);
                         actionSetActiveBindings.add(binding);
                     }
                 } else if (actionSetActiveBindings.contains(binding)) {
                     bindingService.removeBinding(binding);
                     actionSetActiveBindings.remove(binding);
                 }
             }
         }
     };
     
     /**
      * Map every commandId to its binding.
      */
     private HashMap commandIdToBinding = new HashMap ();
     
     /**
      * Which bindings do we currently have outstanding.
      */
     private HashSet actionSetActiveBindings = new HashSet ();

     /**
      * Constructs a new instance of {@link LegacyActionPersistence}.
      *
      * @param window
      * The window from which the services should be retrieved; must
      * not be <code>null</code>.
      */
     public LegacyActionPersistence(final IWorkbenchWindow window) {
         // TODO Blind casts are bad.
 this.bindingService = (BindingService) window
                 .getService(IBindingService.class);

         this.commandService = (ICommandService) window
                 .getService(ICommandService.class);
         this.window = window;
     }

     /**
      * Deactivates all of the activations made by this class, and then clears
      * the collection. This should be called before every read.
      */
     private final void clearActivations() {
         final IHandlerService service = (IHandlerService) window
                 .getService(IHandlerService.class);
         service.deactivateHandlers(handlerActivations);
         final Iterator activationItr = handlerActivations.iterator();
         while (activationItr.hasNext()) {
             final IHandlerActivation activation = (IHandlerActivation) activationItr
                     .next();
             final IHandler handler = activation.getHandler();
             if (handler != null) {
                 handler.dispose();
             }
         }
         handlerActivations.clear();
     }

     /**
      * Removes all of the bindings made by this class, and then clears the
      * collection. This should be called before every read.
      */
     private final void clearBindings() {
         Iterator i = commandIdToBinding.entrySet().iterator();
         while (i.hasNext()) {
             Map.Entry entry = (Map.Entry ) i.next();
             String commandId = (String ) entry.getKey();
             Binding binding = (Binding) entry.getValue();
             commandService.getCommand(commandId).removeCommandListener(actionSetListener);
             if (binding!=null && actionSetActiveBindings.contains(binding)) {
                 bindingService.removeBinding(binding);
             }
         }
         commandIdToBinding.clear();
         actionSetActiveBindings.clear();
     }

     /**
      * Removes all of the image bindings made by this class, and then clears the
      * collection. This should be called before every read.
      *
      */
     private final void clearImages() {
         // TODO Implement
 }

     /**
      * Removes all of the contributions made by this class, and then clears the
      * collection. This should be called before every read.
      */
     private final void clearMenus() {
         menuContributions.clear();
     }

     /**
      * Extracts any key bindings from the action. If such a binding exists, it
      * is added to the binding manager.
      *
      * @param element
      * The action from which the binding should be read; must not be
      * <code>null</code>.
      * @param command
      * The fully-parameterized command for which a binding should be
      * made; must not be <code>null</code>.
      */
     private final void convertActionToBinding(
             final IConfigurationElement element,
             final ParameterizedCommand command, final List warningsToLog) {
         // Figure out which accelerator text to use.
 String acceleratorText = readOptional(element, ATT_ACCELERATOR);
         if (acceleratorText == null) {
             final String label = readOptional(element, ATT_LABEL);
             if (label != null) {
                 acceleratorText = LegacyActionTools
                         .extractAcceleratorText(label);
             }
         }

         // If there is some accelerator text, generate a key sequence from it.
 if (acceleratorText != null) {
             final IKeyLookup lookup = KeyLookupFactory.getSWTKeyLookup();
             final int acceleratorInt = LegacyActionTools
                     .convertAccelerator(acceleratorText);
             final int modifierMask = lookup.getAlt() | lookup.getCommand()
                     | lookup.getCtrl() | lookup.getShift();
             final int modifierKeys = acceleratorInt & modifierMask;
             final int naturalKey = acceleratorInt & ~modifierMask;
             final KeyStroke keyStroke = KeyStroke.getInstance(modifierKeys,
                     naturalKey);
             final KeySequence keySequence = KeySequence.getInstance(keyStroke);

             final Scheme activeScheme = bindingService.getActiveScheme();

             try {
                 final Binding binding = new KeyBinding(keySequence, command,
                         activeScheme.getId(), IContextIds.CONTEXT_ID_WINDOW,
                         null, null, null, Binding.SYSTEM);
                 commandIdToBinding.put(command.getCommand().getId(), binding);

                 if (command.getCommand().isEnabled()) {
                     bindingService.addBinding(binding);
                     actionSetActiveBindings.add(binding);
                 }

                 command.getCommand().addCommandListener(actionSetListener);
             } catch (IllegalArgumentException e) {
                 addWarning(warningsToLog,
                         "invalid keybinding: " + e.getMessage(), element, //$NON-NLS-1$
 command.getCommand().getId());
             }
         }
     }

     /**
      * Determine which command to use. This is slightly complicated as actions
      * do not have to have commands, but the new architecture requires it. As
      * such, we will auto-generate a command for the action if the definitionId
      * is missing or points to a command that does not yet exist. All such
      * command identifiers are prefixed with AUTOGENERATED_COMMAND_ID_PREFIX.
      *
      * @param element
      * The action element from which a command must be generated;
      * must not be <code>null</code>.
      * @param primaryId
      * The primary identifier to use when auto-generating a command;
      * must not be <code>null</code>.
      * @param secondaryId
      * The secondary identifier to use when auto-generating a
      * command; must not be <code>null</code>.
      * @param warningsToLog
      * The collection of warnings logged while reading the extension
      * point; must not be <code>null</code>.
      * @return the fully-parameterized command; <code>null</code> if an error
      * occurred.
      */
     private final ParameterizedCommand convertActionToCommand(
             final IConfigurationElement element, final String primaryId,
             final String secondaryId, final List warningsToLog) {
         String commandId = readOptional(element, ATT_DEFINITION_ID);
         Command command = null;
         if (commandId != null) {
             command = commandService.getCommand(commandId);
         }

         final IActionCommandMappingService mappingService = (IActionCommandMappingService) window
                 .getService(IActionCommandMappingService.class);
         
         String label = null;
         if ((commandId == null) || (!command.isDefined())) {
             // Add a mapping from this action id to the command id.
 if (commandId == null && mappingService != null) {
                 commandId = mappingService.getGeneratedCommandId(primaryId,
                         secondaryId);
             }
             if (commandId == null) {
                 WorkbenchPlugin.log("MappingService unavailable"); //$NON-NLS-1$
 return null;
             }

             // Read the label attribute.
 label = readRequired(element, ATT_LABEL, warningsToLog,
                     "Actions require a non-empty label or definitionId", //$NON-NLS-1$
 commandId);
             if (label == null) {
                 label = WorkbenchMessages.LegacyActionPersistence_AutogeneratedCommandName;
             }

             /*
              * Read the tooltip attribute. The tooltip is really the description
              * of the command.
              */
             final String tooltip = readOptional(element, ATT_TOOLTIP);

             // Define the command.
 command = commandService.getCommand(commandId);
             final Category category = commandService.getCategory(null);
             final String name = LegacyActionTools.removeAcceleratorText(Action
                     .removeMnemonics(label));
             command.define(name, tooltip, category, null);

             // TODO Decide the command state.
 final String style = readOptional(element, ATT_STYLE);
             if (STYLE_RADIO.equals(style)) {
                 final State state = new RadioState();
                 // TODO How to set the id?
 final boolean checked = readBoolean(element, ATT_STATE, false);
                 state.setValue((checked) ? Boolean.TRUE : Boolean.FALSE);
                 command.addState(IMenuStateIds.STYLE, state);

             } else if (STYLE_TOGGLE.equals(style)) {
                 final State state = new ToggleState();
                 final boolean checked = readBoolean(element, ATT_STATE, false);
                 state.setValue((checked) ? Boolean.TRUE : Boolean.FALSE);
                 command.addState(IMenuStateIds.STYLE, state);
             }
         }
         // this allows us to look up a "commandId" give the contributionId
 // and the actionId
 if (mappingService != null && commandId != null) {
             mappingService.map(mappingService.getGeneratedCommandId(primaryId,
                     secondaryId), commandId);
         }

         return new ParameterizedCommand(command, null);
     }

     /**
      * <p>
      * Extracts the handler information from the given action element. These are
      * registered with the handler service. They are always active.
      * </p>
      *
      * @param element
      * The action element from which the handler should be read; must
      * not be <code>null</code>.
      * @param actionId
      * The identifier of the action for which a handler is being
      * created; must not be <code>null</code>.
      * @param command
      * The command for which this handler applies; must not be
      * <code>null</code>.
      * @param activeWhenExpression
      * The expression controlling when the handler is active; may be
      * <code>null</code>.
      * @param viewId
      * The view to which this handler is associated. This value is
      * required if this is a view action; otherwise it can be
      * <code>null</code>.
      * @param warningsToLog
      * The collection of warnings while parsing this extension point;
      * must not be <code>null</code>.
      */
     private final void convertActionToHandler(
             final IConfigurationElement element, final String actionId,
             final ParameterizedCommand command,
             final Expression activeWhenExpression, final String viewId,
             final List warningsToLog) {
         // Check to see if this is a retargettable action.
 final boolean retarget = readBoolean(element, ATT_RETARGET, false);

         final boolean classAvailable = (element.getAttribute(ATT_CLASS) != null)
                 || (element.getChildren(TAG_CLASS).length != 0);
         // Read the class attribute.
 String classString = readOptional(element, ATT_CLASS);
         if (classAvailable && classString == null) {
             classString = readOptional(element.getChildren(TAG_CLASS)[0],
                     ATT_CLASS);
         }

         if (retarget) {
             if (classAvailable && !isPulldown(element)) {
                 addWarning(warningsToLog,
                         "The class was not null but retarget was set to true", //$NON-NLS-1$
 element, actionId, ATT_CLASS, classString);
             }

             // Add a mapping from this action id to the command id.
 final IActionCommandMappingService mappingService = (IActionCommandMappingService) window
                     .getService(IActionCommandMappingService.class);
             if (mappingService != null) {
                 mappingService.map(actionId, command.getId());
             } else {
                 // this is probably the shutdown case where the service has
 // already disposed.
 addWarning(
                         warningsToLog,
                         "Retarget service unavailable", //$NON-NLS-1$
 element, actionId);
             }
             return; // This is nothing more to be done.

         } else if (!classAvailable) {
             addWarning(
                     warningsToLog,
                     "There was no class provided, and the action is not retargettable", //$NON-NLS-1$
 element, actionId);
             return; // There is nothing to be done.
 }

         // Read the enablesFor attribute, and enablement and selection elements.
 SelectionEnabler enabler = null;
         if (element.getAttribute(ATT_ENABLES_FOR) != null) {
             enabler = new SelectionEnabler(element);
         } else {
             IConfigurationElement[] kids = element.getChildren(TAG_ENABLEMENT);
             if (kids.length > 0) {
                 enabler = new SelectionEnabler(element);
             }
         }
         final Expression enabledWhenExpression;
         if (enabler == null) {
             enabledWhenExpression = null;
         } else {
             enabledWhenExpression = new LegacySelectionEnablerWrapper(enabler,
                     window);
         }

         /*
          * Create the handler. TODO The image style is read at the workbench
          * level, but it is hard to communicate this information to this point.
          * For now, I'll pass null, but this ultimately won't work.
          */
         final ActionDelegateHandlerProxy handler = new ActionDelegateHandlerProxy(
                 element, ATT_CLASS, actionId, command, window, null,
                 enabledWhenExpression, viewId);

         // Read the help context id.
 final String helpContextId = readOptional(element, ATT_HELP_CONTEXT_ID);
         if (helpContextId != null) {
             commandService.setHelpContextId(handler, helpContextId);
         }

         // Activate the handler.
 final String commandId = command.getId();
         final IHandlerService service = (IHandlerService) window
                 .getService(IHandlerService.class);
         final IHandlerActivation handlerActivation;
         if (activeWhenExpression == null) {
             handlerActivation = service.activateHandler(commandId, handler);
         } else {
             handlerActivation = service.activateHandler(commandId, handler,
                     activeWhenExpression);
         }
         handlerActivations.add(handlerActivation);
     }



     public final void dispose() {
         super.dispose();
         clear();
     }

     private void clear() {
         clearActivations();
         clearBindings();
         clearImages();
         clearMenus();
     }

     protected final boolean isChangeImportant(final IRegistryChangeEvent event) {
         return !((event.getExtensionDeltas(PlatformUI.PLUGIN_ID,
                 IWorkbenchRegistryConstants.PL_ACTION_SETS).length == 0)
                 && (event.getExtensionDeltas(PlatformUI.PLUGIN_ID,
                         IWorkbenchRegistryConstants.PL_EDITOR_ACTIONS).length == 0)
                 && (event.getExtensionDeltas(PlatformUI.PLUGIN_ID,
                         IWorkbenchRegistryConstants.PL_POPUP_MENU).length == 0) && (event
                 .getExtensionDeltas(PlatformUI.PLUGIN_ID,
                         IWorkbenchRegistryConstants.PL_VIEW_ACTIONS).length == 0));
     }

     /**
      * <p>
      * Reads all of the actions from the deprecated extension points. Actions
      * have been replaced with commands, command images, handlers, menu elements
      * and action sets.
      * </p>
      * <p>
      * TODO Before this method is called, all of the extension points must be
      * cleared.
      * </p>
      */
     public final void read() {
         clear();
         LegacyActionPersistence.super.read();

         // Create the extension registry mementos.
 final IExtensionRegistry registry = Platform.getExtensionRegistry();
         int actionSetCount = 0;
         int editorContributionCount = 0;
         int objectContributionCount = 0;
         int viewContributionCount = 0;
         int viewerContributionCount = 0;
         final IConfigurationElement[][] indexedConfigurationElements = new IConfigurationElement[5][];

         // Sort the actionSets extension point.
 final IConfigurationElement[] actionSetsExtensionPoint = registry
                 .getConfigurationElementsFor(EXTENSION_ACTION_SETS);
         for (int i = 0; i < actionSetsExtensionPoint.length; i++) {
             final IConfigurationElement element = actionSetsExtensionPoint[i];
             final String name = element.getName();
             if (TAG_ACTION_SET.equals(name)) {
                 addElementToIndexedArray(element, indexedConfigurationElements,
                         INDEX_ACTION_SETS, actionSetCount++);
             }
         }

         // Sort the editorActions extension point.
 final IConfigurationElement[] editorActionsExtensionPoint = registry
                 .getConfigurationElementsFor(EXTENSION_EDITOR_ACTIONS);
         for (int i = 0; i < editorActionsExtensionPoint.length; i++) {
             final IConfigurationElement element = editorActionsExtensionPoint[i];
             final String name = element.getName();
             if (TAG_EDITOR_CONTRIBUTION.equals(name)) {
                 addElementToIndexedArray(element, indexedConfigurationElements,
                         INDEX_EDITOR_CONTRIBUTIONS, editorContributionCount++);
             }
         }

         // Sort the popupMenus extension point.
 final IConfigurationElement[] popupMenusExtensionPoint = registry
                 .getConfigurationElementsFor(EXTENSION_POPUP_MENUS);
         for (int i = 0; i < popupMenusExtensionPoint.length; i++) {
             final IConfigurationElement element = popupMenusExtensionPoint[i];
             final String name = element.getName();
             if (TAG_OBJECT_CONTRIBUTION.equals(name)) {
                 addElementToIndexedArray(element, indexedConfigurationElements,
                         INDEX_OBJECT_CONTRIBUTIONS, objectContributionCount++);
             } else if (TAG_VIEWER_CONTRIBUTION.equals(name)) {
                 addElementToIndexedArray(element, indexedConfigurationElements,
                         INDEX_VIEWER_CONTRIBUTIONS, viewerContributionCount++);
             }
         }

         // Sort the viewActions extension point.
 final IConfigurationElement[] viewActionsExtensionPoint = registry
                 .getConfigurationElementsFor(EXTENSION_VIEW_ACTIONS);
         for (int i = 0; i < viewActionsExtensionPoint.length; i++) {
             final IConfigurationElement element = viewActionsExtensionPoint[i];
             final String name = element.getName();
             if (TAG_VIEW_CONTRIBUTION.equals(name)) {
                 addElementToIndexedArray(element, indexedConfigurationElements,
                         INDEX_VIEW_CONTRIBUTIONS, viewContributionCount++);
             }
         }

         readActionSets(indexedConfigurationElements[INDEX_ACTION_SETS],
                 actionSetCount);
         readEditorContributions(
                 indexedConfigurationElements[INDEX_EDITOR_CONTRIBUTIONS],
                 editorContributionCount);
         readObjectContributions(
                 indexedConfigurationElements[INDEX_OBJECT_CONTRIBUTIONS],
                 objectContributionCount);
         readViewContributions(
                 indexedConfigurationElements[INDEX_VIEW_CONTRIBUTIONS],
                 viewContributionCount);
         readViewerContributions(
                 indexedConfigurationElements[INDEX_VIEWER_CONTRIBUTIONS],
                 viewerContributionCount);
         
     }

     /**
      * Reads the actions, and defines all the necessary subcomponents in terms
      * of the command architecture. For each action, there could be a command, a
      * command image binding, a handler and a menu item.
      *
      * @param primaryId
      * The identifier of the primary object to which this action
      * belongs. This is used to auto-generate command identifiers
      * when required. The <code>primaryId</code> must not be
      * <code>null</code>.
      * @param elements
      * The action elements to be read; must not be <code>null</code>.
      * @param warningsToLog
      * The collection of warnings while parsing this extension point;
      * must not be <code>null</code>.
      * @param visibleWhenExpression
      * The expression controlling visibility of the corresponding
      * menu elements; may be <code>null</code>.
      * @param viewId
      * The view to which this handler is associated. This value is
      * required if this is a view action; otherwise it can be
      * <code>null</code>.
      * @return References to the created menu elements; may be <code>null</code>,
      * and may be empty.
      */
     private final void readActions(final String primaryId,
             final IConfigurationElement[] elements, final List warningsToLog,
             final Expression visibleWhenExpression, final String viewId) {
         for (int i = 0; i < elements.length; i++) {
             final IConfigurationElement element = elements[i];

             /*
              * We might need the identifier to generate the command, so we'll
              * read it out now.
              */
             final String id = readRequired(element, ATT_ID, warningsToLog,
                     "Actions require an id"); //$NON-NLS-1$
 if (id == null) {
                 continue;
             }

             // Try to break out the command part of the action.
 final ParameterizedCommand command = convertActionToCommand(
                     element, primaryId, id, warningsToLog);
             if (command == null) {
                 continue;
             }

             convertActionToHandler(element, id, command, visibleWhenExpression,
                     viewId, warningsToLog);
             // TODO Read the overrideActionId attribute

             convertActionToBinding(element, command, warningsToLog);

         }
     }

     /**
      * Reads all of the action and menu child elements from the given element.
      *
      * @param element
      * The configuration element from which the actions and menus
      * should be read; must not be <code>null</code>, but may be
      * empty.
      * @param id
      * The identifier of the contribution being made. This could be
      * an action set, an editor contribution, a view contribution, a
      * viewer contribution or an object contribution. This value must
      * not be <code>null</code>.
      * @param warningsToLog
      * The list of warnings already logged for this extension point;
      * must not be <code>null</code>.
      * @param visibleWhenExpression
      * The expression controlling visibility of the corresponding
      * menu elements; may be <code>null</code>.
      * @param viewId
      * The view to which this handler is associated. This value is
      * required if this is a view action; otherwise it can be
      * <code>null</code>.
      * @return An array of references to the created menu elements. This value
      * may be <code>null</code> if there was a problem parsing the
      * configuration element.
      */
     private final void readActionsAndMenus(
             final IConfigurationElement element, final String id,
             final List warningsToLog,
             final Expression visibleWhenExpression, final String viewId) {

         // Read its child elements.
 final IConfigurationElement[] actionElements = element
                 .getChildren(TAG_ACTION);
         readActions(id, actionElements,
                 warningsToLog, visibleWhenExpression, viewId);

     }

     /**
      * Reads the deprecated actions from an array of elements from the action
      * sets extension point.
      *
      * @param configurationElements
      * The configuration elements in the extension point; must not be
      * <code>null</code>, but may be empty.
      * @param configurationElementCount
      * The number of configuration elements that are really in the
      * array.
      */
     private final void readActionSets(
             final IConfigurationElement[] configurationElements,
             final int configurationElementCount) {
         //
 // this was an even dumber fix than modifying the path
 //
 // stupid navigate group
 // SGroup nav = menuService.getGroup(STUPID_NAVIGATE);
 // if (!nav.isDefined()) {
 // nav.define(new SLocation(new SBar(SBar.TYPE_MENU, null)));
 // }
 // stupid navigate group

         final List warningsToLog = new ArrayList (1);

         for (int i = 0; i < configurationElementCount; i++) {
             final IConfigurationElement element = configurationElements[i];

             // Read the action set identifier.
 final String id = readRequired(element, ATT_ID, warningsToLog,
                     "Action sets need an id"); //$NON-NLS-1$
 if (id == null) {
                 continue;
             }

             // Read the label.
 final String label = readRequired(element, ATT_LABEL,
                     warningsToLog, "Actions set need a label", //$NON-NLS-1$
 id);
             if (label == null) {
                 continue;
             }

             // Restrict the handler to when the action set is active.
 final LegacyActionSetExpression expression = new LegacyActionSetExpression(
                     id, window);


             // Read all of the child elements.
 readActionsAndMenus(element, id,
                     warningsToLog, expression, null);
             // Define the action set.
 }

         logWarnings(
                 warningsToLog,
                 "Warnings while parsing the action sets from the 'org.eclipse.ui.actionSets' extension point"); //$NON-NLS-1$
 }

     /**
      * Reads the deprecated editor contributions from an array of elements from
      * the editor actions extension point.
      *
      * @param configurationElements
      * The configuration elements in the extension point; must not be
      * <code>null</code>, but may be empty.
      * @param configurationElementCount
      * The number of configuration elements that are really in the
      * array.
      */
     private final void readEditorContributions(
             final IConfigurationElement[] configurationElements,
             final int configurationElementCount) {
         final List warningsToLog = new ArrayList (1);

         for (int i = 0; i < configurationElementCount; i++) {
             final IConfigurationElement element = configurationElements[i];

             // Read the editor contribution identifier.
 final String id = readRequired(element, ATT_ID, warningsToLog,
                     "Editor contributions need an id"); //$NON-NLS-1$
 if (id == null) {
                 continue;
             }

             /*
              * Read the target id. This is the identifier of the editor with
              * which these contributions are associated.
              */
             final String targetId = readRequired(element, ATT_TARGET_ID,
                     warningsToLog, "Editor contributions need a target id", id); //$NON-NLS-1$
 if (targetId == null) {
                 continue;
             }
             final Expression visibleWhenExpression = new LegacyEditorContributionExpression(
                     targetId, window);

             // Read all of the child elements from the registry.
 readActionsAndMenus(element, id, warningsToLog,
                     visibleWhenExpression, null);
         }

         logWarnings(
                 warningsToLog,
                 "Warnings while parsing the editor contributions from the 'org.eclipse.ui.editorActions' extension point"); //$NON-NLS-1$
 }




     /**
      * Reads the deprecated object contributions from an array of elements from
      * the popup menus extension point.
      *
      * @param configurationElements
      * The configuration elements in the extension point; must not be
      * <code>null</code>, but may be empty.
      * @param configurationElementCount
      * The number of configuration elements that are really in the
      * array.
      */
     private final void readObjectContributions(
             final IConfigurationElement[] configurationElements,
             final int configurationElementCount) {
         final List warningsToLog = new ArrayList (1);

         for (int i = 0; i < configurationElementCount; i++) {
             final IConfigurationElement element = configurationElements[i];

             // Read the object contribution identifier.
 final String id = readRequired(element, ATT_ID, warningsToLog,
                     "Object contributions need an id"); //$NON-NLS-1$
 if (id == null) {
                 continue;
             }

             // Read the object class. This influences the visibility.
 final String objectClass = readRequired(element, ATT_OBJECTCLASS,
                     warningsToLog,
                     "Object contributions need an object class", id); //$NON-NLS-1$
 if (objectClass == null) {
                 continue;
             }

             // TODO Read the name filter. This influences the visibility.
 // final String nameFilter = readOptional(element,
 // ATT_NAME_FILTER);

             // TODO Read the object class. This influences the visibility.
 // final boolean adaptable = readBoolean(element,
 // ATT_ADAPTABLE,
 // false);


             // TODO Read the filter elements.
 // TODO Read the enablement elements.

             // TODO Figure out an appropriate visibility expression.
 // Read the visibility element, if any.
 final Expression visibleWhenExpression = readVisibility(element,
                     id, warningsToLog);

             // Read all of the child elements from the registry.
 readActionsAndMenus(element, id, warningsToLog,
                     visibleWhenExpression, null);
         }

         logWarnings(
                 warningsToLog,
                 "Warnings while parsing the object contributions from the 'org.eclipse.ui.popupMenus' extension point"); //$NON-NLS-1$
 }

     /**
      * Reads the deprecated view contributions from an array of elements from
      * the view actions extension point.
      *
      * @param configurationElements
      * The configuration elements in the extension point; must not be
      * <code>null</code>, but may be empty.
      * @param configurationElementCount
      * The number of configuration elements that are really in the
      * array.
      */
     private final void readViewContributions(
             final IConfigurationElement[] configurationElements,
             final int configurationElementCount) {
         final List warningsToLog = new ArrayList (1);

         for (int i = 0; i < configurationElementCount; i++) {
             final IConfigurationElement element = configurationElements[i];

             // Read the view contribution identifier.
 final String id = readRequired(element, ATT_ID, warningsToLog,
                     "View contributions need an id"); //$NON-NLS-1$
 if (id == null) {
                 continue;
             }

             /*
              * Read the target id. This is the identifier of the view with which
              * these contributions are associated.
              */
             final String targetId = readRequired(element, ATT_TARGET_ID,
                     warningsToLog, "View contributions need a target id", id); //$NON-NLS-1$
 if (targetId == null) {
                 continue;
             }
             final Expression visibleWhenExpression = new LegacyViewContributionExpression(
                     targetId, window);

             // Read all of the child elements from the registry.
 readActionsAndMenus(element, id, warningsToLog,
                     visibleWhenExpression, targetId);
         }

         logWarnings(
                warningsToLog,
                "Warnings while parsing the view contributions from the 'org.eclipse.ui.viewActions' extension point"); //$NON-NLS-1$
 }

    /**
     * Reads the deprecated viewer contributions from an array of elements from
     * the popup menus extension point.
     *
     * @param configurationElements
     * The configuration elements in the extension point; must not be
     * <code>null</code>, but may be empty.
     * @param configurationElementCount
     * The number of configuration elements that are really in the
     * array.
     */
    private final void readViewerContributions(
            final IConfigurationElement[] configurationElements,
            final int configurationElementCount) {
        final List warningsToLog = new ArrayList (1);

        for (int i = 0; i < configurationElementCount; i++) {
            final IConfigurationElement element = configurationElements[i];

            // Read the viewer contribution identifier.
 final String id = readRequired(element, ATT_ID, warningsToLog,
                    "Viewer contributions need an id"); //$NON-NLS-1$
 if (id == null) {
                continue;
            }

            /*
             * Read the target id. This is the identifier of the view with which
             * these contributions are associated.
             */
            final String targetId = readRequired(element, ATT_TARGET_ID,
                    warningsToLog, "Viewer contributions need a target id", id); //$NON-NLS-1$
 if (targetId == null) {
                continue;
            }

            // Read the visibility element, if any.
 final Expression visibleWhenExpression = readVisibility(element,
                    id, warningsToLog);
            final Expression menuVisibleWhenExpression = new LegacyViewerContributionExpression(
                    targetId, window, visibleWhenExpression);

            // Read all of the child elements from the registry.
 readActionsAndMenus(element, id, warningsToLog,
                    menuVisibleWhenExpression, targetId);
        }

        logWarnings(
                warningsToLog,
                "Warnings while parsing the viewer contributions from the 'org.eclipse.ui.popupMenus' extension point"); //$NON-NLS-1$
 }
}

